﻿#include "MaterialDialogIsoSoild.h"
#include "ui_MaterialDialogIsoSoild.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsMaterialsIsosolid.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsMaterial.h"
#include <QMessageBox>
#include <QRegExpValidator>
namespace GUI
{
    MaterialDialogIsoSoild::MaterialDialogIsoSoild(PhysicsDlgExecType type, int matid /*= -1*/, QWidget* parent /*= nullptr*/)
        :AbstractMaterialDialog(type, parent)
    {
        _ui = new Ui::MaterialDialogIsoSoild;
        _ui->setupUi(this);
        //获取材料对象
        if (_matMgr && matid > 0)
            _mat = dynamic_cast<Acoustics::FITKAcousticsMaterialsIsosolid*>(_matMgr->getDataByID(matid));

        this->init();

    }

    MaterialDialogIsoSoild::~MaterialDialogIsoSoild()
    {
        if (_ui) delete _ui;
    }

    void MaterialDialogIsoSoild::on_pushButtonOK_clicked()
    {
        if (!this->checkInput()) return;
        //要处理的对象
        Acoustics::FITKAcousticsMaterialsIsosolid* iso = dynamic_cast<Acoustics::FITKAcousticsMaterialsIsosolid*>(_mat);
        //保存执行的脚本
        QStringList str;
        QString name = _ui->lineEdit_Name->text();
        //创建与复制,创建新对象
        if (_execType == GUI::PhysicsDlgExecType::Create || _execType == GUI::PhysicsDlgExecType::Duplicate)
        {
            str.append("m=Material.IsotropicSolids()");
            str.append(QString("m.createMaterial('%1')").arg(name));
            iso = new Acoustics::FITKAcousticsMaterialsIsosolid;
            _matMgr->appendDataObj(iso);
        }
        if (!iso)return;

        //保存数据
        double density= _ui->lineEdit_Density->text().toDouble();
        double E= _ui->lineEdit_TensileModulus->text().toDouble();
        double G= _ui->lineEdit_ShearModulus->text().toDouble();
        double poissonRatio= std::round(_ui->lineEdit_PoissonRatio->text().toDouble()* 10000.0) / 10000.0;

        if (_execType == GUI::PhysicsDlgExecType::Edit)
        {
            str.append(QString("m=Material.IsotropicSolids.GetIsotropicSolids('%1')").arg(iso->getDataObjectName()));
            str.append(QString("m.setName('%1')").arg(name));
        }
        str.append(QString("m.setIsotropicSolidsProp(%1,%2,%3,%4)").arg(density).arg(E).arg(G).arg(poissonRatio));

        iso->setDataObjectName(name);
        iso->setDensity(density);
        iso->setPoissonRatio(poissonRatio);
        iso->setTensileModulus(E);
        iso->setShearModulus(G);

        this->saveScript(str);
        this->accept();
    }

    void MaterialDialogIsoSoild::on_pushButtonCancel_clicked()
    {
        this->reject();
    }

    void MaterialDialogIsoSoild::slot_radioButton_clicked(bool checked)
    {
        // 忽略checked参数，在此函数中未使用
        Q_UNUSED(checked);
        // 根据选中的单选按钮启用或禁用剪切模量和泊松比的输入框
        _ui->lineEdit_ShearModulus->setEnabled(_ui->radioButton_ShearModulus->isChecked());
        _ui->lineEdit_PoissonRatio->setEnabled(_ui->radioButton_PoissonRatio->isChecked());
    }

    void MaterialDialogIsoSoild::slot_lineEdit_textChanged(const QString & arg1)
    {
        // 获取发送信号的QLineEdit
        QLineEdit *lineEditSender = qobject_cast<QLineEdit*>(sender());
        if (!lineEditSender || arg1.isEmpty()) return;
        // 断开当前文本更改信号，避免递归调用
        disconnect(_ui->lineEdit_PoissonRatio, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        disconnect(_ui->lineEdit_ShearModulus, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        disconnect(_ui->lineEdit_TensileModulus, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        // 获取各个材料属性的值
        double e = _ui->lineEdit_TensileModulus->text().toDouble();
        double v = _ui->lineEdit_PoissonRatio->text().toDouble();
        double g = _ui->lineEdit_ShearModulus->text().toDouble();
        // 进行数据相关计算
        if ((lineEditSender == _ui->lineEdit_TensileModulus && _ui->radioButton_PoissonRatio->isChecked()) ||
            lineEditSender == _ui->lineEdit_PoissonRatio)
        {
            double g = e / (2 + 2 * v);
            _ui->lineEdit_ShearModulus->setText(QString::number(g));
        }
        else if ((lineEditSender == _ui->lineEdit_TensileModulus && _ui->radioButton_ShearModulus->isChecked()) ||
            lineEditSender == _ui->lineEdit_ShearModulus)
        {
            if (g != 0 && v != 0)
            {
                v = e / (2 * g) - 1;
                _ui->lineEdit_PoissonRatio->setText(QString::number(v));
            }
        }
        // 重新连接文本更改信号
        connect(_ui->lineEdit_PoissonRatio, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        connect(_ui->lineEdit_ShearModulus, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        connect(_ui->lineEdit_TensileModulus, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
    }

    void MaterialDialogIsoSoild::init()
    {
        if (_matMgr == nullptr) return;

        if (_execType == GUI::PhysicsDlgExecType::Create)
        {
            QString name = _matMgr->checkName("New Isotropic Solid Material");
            _ui->lineEdit_Name->setText(name);
        }

        Acoustics::FITKAcousticsMaterialsIsosolid* iso = dynamic_cast<Acoustics::FITKAcousticsMaterialsIsosolid*>(_mat);
        if (!iso)return;
        
        // 设置各个属性的值
        _ui->lineEdit_Name->setText(iso->getDataObjectName());
        _ui->lineEdit_Density->setText(QString::number(iso->getDensity()));
        _ui->lineEdit_TensileModulus->setText(QString::number(iso->getTensileModulus()));
        _ui->lineEdit_ShearModulus->setText(QString::number(iso->getShearModulus()));
        _ui->lineEdit_PoissonRatio->setText(QString::number(iso->getPoissonRatio()));

        connect(_ui->radioButton_PoissonRatio, &QRadioButton::clicked, this, &MaterialDialogIsoSoild::slot_radioButton_clicked);
        connect(_ui->radioButton_ShearModulus, &QRadioButton::clicked, this, &MaterialDialogIsoSoild::slot_radioButton_clicked);
        connect(_ui->lineEdit_PoissonRatio, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        connect(_ui->lineEdit_ShearModulus, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);
        connect(_ui->lineEdit_TensileModulus, &QLineEdit::textChanged, this, &MaterialDialogIsoSoild::slot_lineEdit_textChanged);

        //复制,更新名称
        if (_execType == GUI::PhysicsDlgExecType::Duplicate)
        {
            QString text = QString("Copy of %1").arg(iso->getDataObjectName());
            _ui->lineEdit_Name->setText(text);
        }
    }

    bool MaterialDialogIsoSoild::checkInput()
    {
        //检查数据合法性
        QList<QLineEdit*> checkUi;
        checkUi  << _ui->lineEdit_Density << _ui->lineEdit_TensileModulus
            << _ui->lineEdit_ShearModulus << _ui->lineEdit_PoissonRatio;
        for (QLineEdit* e : checkUi)
        {
            if (e == nullptr) continue;
            QString text = e->text().trimmed();
            bool ok = false;
            text.toDouble(&ok);
            if (!ok)
            {
                QMessageBox::critical(nullptr, tr("Critical"), tr("Please enter a number."));
                return false;
            }
        }
        double v = _ui->lineEdit_PoissonRatio->text().toDouble();
        double g = _ui->lineEdit_ShearModulus->text().toDouble();
        double e = _ui->lineEdit_TensileModulus->text().toDouble();
        // 检测数据是否合理
        if (v <= 0 || v >= 0.5){
            if (_ui->radioButton_PoissonRatio ->isChecked()) {
                QMessageBox::critical(this, tr("Critical"), tr("Poisson's ratio must be greater than zero and less than 0.5."));
                return false;
            }
        }
        if (e < 2 * g || e > 3 * g) {
            if (_ui->radioButton_ShearModulus->isChecked()) {
                QMessageBox::critical(this, tr("Critical"), tr("The tensile modulus E must be greater than 2*G and less than 3*G."));
                return false;
            }
        }

        if (_matMgr == nullptr) return false;
        //检查名称
        QString text = _ui->lineEdit_Name->text().trimmed();
        if (text != "") {
            QString newText = _matMgr->checkName(text);
            if (text == newText) return true;
            //与自己重名
            if (_matMgr->getDataByName(text) == _mat) return true;
        }

        QMessageBox::critical(nullptr, tr("Critical"), tr("Please enter a new Name."));
        return false;
    }


}

